--[[
 -- *名称:ThreeTakePairPlusTypeAnalyzer
 -- *描述:[XXXXXXXXX]
 -- *版权:Copyright © 2016-2018 深圳市三只小熊科技有限公司 版权所有
 -- *作者:Administrator
 -- *创建日期:2017-11-09
 -- *修改日期:2017-11-09
 ]]
local DdzSuitAnalyzer = require(basePath.."suit/ddzsuitanalyzer");
local ThreeStraightTypeAnalyzer = require(basePath.."suit/threestraight/threestraighttypeanalyzer")
local ThreeTakePairPlusTypeAnalyzer = pokercore.class(DdzSuitAnalyzer,false);
local FourTakePairTypeAnalyzer = require(basePath.."suit/fourtakepair/fourtakepairtypeanalyzer");  --四带二
local fourTakePairTypeAnalyzer = pokercore.new(FourTakePairTypeAnalyzer);
local ThreeTypeAnalyzer = require(basePath.."suit/three/threetypeanalyzer"); --三条
local Cards = require(basePath .. "domain/cards");
ThreeTakePairPlusTypeAnalyzer.LIMIT_SIZE = 10 ;

ThreeTakePairPlusTypeAnalyzer.TUPLE_SIZE = 5 ;
local LIMIT_SIZE = 10 ;
local TUPLE_SIZE = 5 ;

--@Override
function ThreeTakePairPlusTypeAnalyzer:getSuitType()
	return DdzCardTypes.THREE_TAKE_PAIR_PLUS;
end


--@Override
function ThreeTakePairPlusTypeAnalyzer:doCheckRule(cards,term,result)
	if (result:getCardNum() >= ThreeTakePairPlusTypeAnalyzer.LIMIT_SIZE and result:getCardNum() % ThreeTakePairPlusTypeAnalyzer.TUPLE_SIZE == 0) then
		if (result:isAllCardLazi()) then -- // 全部癞子默认炸弹
			return false;
		end
		local allValues = result:getNoneLaziValueCounter():getAllValues();
		if (#allValues == 1) then -- // 3*******  5555*** 默认炸弹
			return false;
		end
		if (result:getNoneLaziValueCounter():hasJoker()) then -- // 非赖部分有王
			return false;
		end
		local tupleNum = result:getCardNum() / ThreeTakePairPlusTypeAnalyzer.TUPLE_SIZE; --// 分析有几组牌，三带一对算做一组
		if (#allValues > (tupleNum * 4)) then 
			--// 考虑情况 3334445555  和  33344455566677778888
			return false;
		end
		--// 遍历寻找所有可能的顺子
		for beginValueTemp = PokerGameConstant.NUMBER_2_VALUE - 1 --// 从A开始
				, PokerGameConstant.NUMBER_3_VALUE + (tupleNum - 1), -1 do
			local beginValueTempNum = result:getNoneLaziValueCounter():getValueCount(beginValueTemp);
			--// 三带二中飞机里，出现四次的点数不会出现在顺子中
			if (beginValueTempNum < 4 and DdzTypeUtil.ensureStaight(beginValueTemp,ThreeTakePairPlusTypeAnalyzer.TUPLE_SIZE, 
					ThreeStraightTypeAnalyzer.TUPLE_SIZE, cards, term, result)) then
				local allNeedLaiziCardNum = 0;
				local straightValues = {} ;
				for valueTemp = beginValueTemp,beginValueTemp - tupleNum+1, -1 do --// 从大到小
					straightValues[valueTemp] = true;
					local valueTempNum = result:getNoneLaziValueCounter():getValueCount(valueTemp);
					local needLaziNum = ThreeStraightTypeAnalyzer.TUPLE_SIZE - valueTempNum;
					needLaziNum = ((needLaziNum > 0) and needLaziNum or 0); -- 防止出现负数
					allNeedLaiziCardNum =  allNeedLaiziCardNum + needLaziNum;
				end
				-- for _, valueTemp in ipairs(allValues) do
				-- 	if not straightValues[valueTemp] 
				-- 	 	and (result:getNoneLaziValueCounter():getValueCount(valueTemp) % 2 ~= 0) then
				-- 		allNeedLaiziCardNum = allNeedLaiziCardNum + 1;
				-- 	end
				-- end
				-- 找出带的牌
				local takeValues = {} ;
				for _, valueTemp in ipairs(allValues) do
					if not straightValues[valueTemp] 
						or (result:getNoneLaziValueCounter():getValueCount(valueTemp) > ThreeStraightTypeAnalyzer.TUPLE_SIZE) then
						takeValues[valueTemp] = true;
					end
				end
				-- 计算需要的癞子数量
				for _, valueTemp in ipairs(allValues) do
					if takeValues[valueTemp] then
						if straightValues[valueTemp] then 
							-- 这张牌在飞机队列且，有3张以上
							if (result:getNoneLaziValueCounter():getValueCount(valueTemp) - ThreeStraightTypeAnalyzer.TUPLE_SIZE) % 2 ~= 0 then 
								allNeedLaiziCardNum = allNeedLaiziCardNum + 1;
							end
						else
							if result:getNoneLaziValueCounter():getValueCount(valueTemp) % 2 ~= 0 then 
								allNeedLaiziCardNum = allNeedLaiziCardNum + 1;
							end
						end
					end
				end
				if (result:getLaziCardNum() >= allNeedLaiziCardNum) then
					return true;
				end
			 end
		 end
		return false;
	else 
		return false;
	end
end

--@Override
function ThreeTakePairPlusTypeAnalyzer:doAnalysizeLaizi(cards,term,onlyMaxValue)
	local cardsResult = {};
	local result = cards:getResult();
	local laiziCardList = cards:subList(result:getCardNum() - result:getLaziCardNum()+1, result:getCardNum())
	----print("ThreeTakePairPlusTypeAnalyzer doAnalysizeLaizi laiziCardList,laiziCardList");
	----dump(laiziCardList,"ThreeTakePairPlusTypeAnalyzer doAnalysizeLaizi laiziCardList,laiziCardList",100);
	local allValues = result:getNoneLaziValueCounter():getAllValues();
	local laiziCardNum = result:getLaziCardNum();
	local tupleNum = result:getCardNum() / ThreeTakePairPlusTypeAnalyzer.TUPLE_SIZE; --// 分析有几组牌，三带一算做一组
	for beginValueTemp = PokerGameConstant.NUMBER_2_VALUE - 1 --// 从A开始
			, PokerGameConstant.NUMBER_3_VALUE + (tupleNum - 1), -1 do
		local beginValueTempNum = result:getNoneLaziValueCounter():getValueCount(beginValueTemp);
		--// 三带二中飞机里，出现四次的点数不会出现在顺子中
		if (beginValueTempNum < 4 and DdzTypeUtil.ensureStaight(beginValueTemp, ThreeTakePairPlusTypeAnalyzer.TUPLE_SIZE, 
				ThreeStraightTypeAnalyzer.TUPLE_SIZE, cards, term, result)) then
			local allNeedLaiziCardNum = 0;
			local laiziCardIndex = 0;
			local straightValues = {} ;
			for valueTemp = beginValueTemp, beginValueTemp - tupleNum + 1, -1 do -- // 从大到小
				result:setSortFirstValue(valueTemp); --// 随着循环确定从哪里开始顺
				straightValues[valueTemp] = true;
				local valueTempNum = result:getNoneLaziValueCounter():getValueCount(valueTemp);
				local needLaziNum = ThreeStraightTypeAnalyzer.TUPLE_SIZE - valueTempNum;
				needLaziNum = ((needLaziNum > 0) and needLaziNum or 0);  --// 防止出现负数
				allNeedLaiziCardNum = allNeedLaiziCardNum + needLaziNum;
				for  i = 1,needLaziNum do
					laiziCardIndex = laiziCardIndex + 1;
					laiziCardList[laiziCardIndex]:changeCard(valueTemp);
				end
			end
			for _,valueTemp in ipairs(allValues) do
				if ((not straightValues[valueTemp]) 
						and (result:getNoneLaziValueCounter():getValueCount(valueTemp) % 2 ~= 0)) then -- // 数量为奇数数牌补成对子
					allNeedLaiziCardNum = allNeedLaiziCardNum + 1;
					if (allNeedLaiziCardNum <= laiziCardNum) then
						laiziCardIndex = laiziCardIndex+ 1;
						laiziCardList[laiziCardIndex]:changeCard(valueTemp);
					else 
						break;
					end
				end
			end
			for i = laiziCardIndex+1,#laiziCardList  do--// 如果有剩余癞子组合成对
				laiziCardList[i]:changeCard(laiziCardList[laiziCardIndex+1]:getNumber());
			end
			if (allNeedLaiziCardNum <= laiziCardNum) then
				--print("################ cards len",#cards:getCardList())
				local cardsCopy = cards:clone();
				self:analysize(cardsCopy, term);
				--print("################ cards len2",#cardsCopy:getCardList())
				table.insert(cardsResult,cardsCopy:clone());
				if (onlyMaxValue) then
					break; --// 取完最大一组就跳出
				end
			end
		end
	end
	return cardsResult;
end

--@Override
function ThreeTakePairPlusTypeAnalyzer:sort(cards,term)
	PokerUtil.sortCards_asc(cards);
	--print("ThreeTakePairPlusTypeAnalyzer:sort->",cards) ;
	--print("######################################",#cards:getCardList()) ;
	local result = cards:getResult();
	local cardlist = cards:getCardList();
	local sortCardList = {}--new ArrayList<Card>(result.getCardNum());
	local firstSortValue = result:getSortFirstValue();
	local tupleNum = math.floor(result:getCardNum() / ThreeTakePairPlusTypeAnalyzer.TUPLE_SIZE); --// 分析有几组牌，三带一算做一组
	for valueTemp = firstSortValue,  firstSortValue + tupleNum -1 do --// 把三顺排好序
		local count = 0;
		for i=#cardlist,1,-1 do
			local card = cardlist[i] ;
			if card:getValue() == valueTemp then				
				table.insert(sortCardList,card);
				table.remove(cardlist,i);
				count = count + 1;
				if count == 3 then
					break; --只要三张
				end
			end
		end
	end
	for i= #sortCardList ,1 ,-1 do
		table.insert(cardlist,1,sortCardList[i]) ;
	end
	--PokerUtil.sortCards_asc(cards);
end



--提牌算法

--@Override
function ThreeTakePairPlusTypeAnalyzer:containsPossibleCards(handCards,term) 
	local result = handCards:getResult();
	if (result:getCardNum() - result:getJokerCardNum() < LIMIT_SIZE) then --// 张数不够
		return false;
	end
	--// 遍历寻找所有可能的顺子
	for beginValueTemp = PokerGameConstant.NUMBER_2_VALUE - 1 --// 从A开始
			,PokerGameConstant.NUMBER_3_VALUE + LIMIT_SIZE / TUPLE_SIZE - 1, -1 do
		if (DdzTypeUtil.ensureTupleStaightDesc(
				beginValueTemp, LIMIT_SIZE / TUPLE_SIZE, ThreeTypeAnalyzer.TUPLE_SIZE, handCards, term, result)) then --// 最低标准顺一下
			return true;
		end
	end
	return false;
end
	
--/** 最多使用癞子的数量 */
local MAX_USE_LAIZI_CARD_NUM = 8;

--/** 防重复判定的比例值 参照 int key = tupleNum * TUPLE_WEIGHT + beginValueTemp; */
local TUPLE_WEIGHT = 1000000;

--/** 癞子权重，区分癞子变成的5 和 原本就是5 */
local LAIZI_WEIGHT = 1000;
	
--@Override
function ThreeTakePairPlusTypeAnalyzer:doListPossibleCards(handCards, term)
	local cardsResult = {};
	--// 非癞子部分
	local result = handCards:getResult();
	local noneLaiziCardList = handCards:subList(1, result:getNoneCardNum());
	local noneLaiziCards = DdzTypeUtil.createCardsCopy(noneLaiziCardList);
	noneLaiziCards:setResult(handCards:getResult():clone());
	local noneLaiziCardsResult = noneLaiziCards:getResult();
	noneLaiziCardsResult:collectNumber(noneLaiziCards, term);
	--// 癞子部分
	local laiziCardList = handCards:subList(result:getNoneCardNum()+1, result:getCardNum());
	local laiziCards = DdzTypeUtil.createCardsCopy(laiziCardList);
	laiziCards:setResult(handCards:getResult():clone());
	
	local laiziCardNum = result:getLaziCardNum();
	local maxUseLaiziCardNum = MAX_USE_LAIZI_CARD_NUM < laiziCardNum and MAX_USE_LAIZI_CARD_NUM or laiziCardNum;
	local exsitKeys = {};
	for useLaiziCardNum = 0,maxUseLaiziCardNum do --// 补几张癞子
		--// 从5顺开始找 10.JQK1 找完找 9.10.J.Q.K.1 在找 8.9.10.J.Q.K.1 
		for tupleNum = LIMIT_SIZE / TUPLE_SIZE
				,(noneLaiziCardsResult:getCardNum() + useLaiziCardNum) / TUPLE_SIZE do
			local partLenResult = {};  --// 部分长度的结果 
			--// 遍历寻找所有可能的顺子  10.J.Q.K.1 找完找 9.10.J.Q.K 在找 8.9.10.J.Q
			for beginValueTemp = PokerGameConstant.NUMBER_2_VALUE - 1 --// 从A开始
					, PokerGameConstant.NUMBER_3_VALUE + tupleNum - 1, -1 do
				local modelCardsCopy = noneLaiziCards:clone(); --// 常规牌副本
				local modelResultCopy = modelCardsCopy:getResult();
				local useLaiziCardsCopy = DdzTypeUtil.cloneSublistedCards(laiziCards, 1, useLaiziCardNum); --// 癞子副本
				table.reverse(useLaiziCardsCopy); -- // 因为这里是倒序赋值，避免 把点数小的癞子牌赋成大值又把点数大的癞子牌赋成小值 的疑惑
				local checkCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardsCopy);-- // 常规牌补上癞子，用于校验顺子
				local checkResult = checkCards:getResult();
				checkResult:collectNumber(checkCards, term); -- // 收集下信息
				local straightKey = tupleNum * TUPLE_WEIGHT + beginValueTemp;
				if (not exsitKeys[straightKey] -- // 每种顺子仅判定一次
						and DdzTypeUtil.ensureTupleStaightDesc(beginValueTemp, tupleNum, ThreeTypeAnalyzer.TUPLE_SIZE, checkCards, term, checkResult)) then
					exsitKeys[straightKey] = true;
					local tupleCards = pokercore.new(Cards);
					local firstSortValue = -1;
					for valueTemp = beginValueTemp,beginValueTemp - tupleNum+1,-1 do -- // 从大到小
						firstSortValue = valueTemp;
						local valueTempNum = modelResultCopy:getNoneLaziValueCounter():getValueCount(valueTemp);
						if (valueTempNum >= ThreeTypeAnalyzer.TUPLE_SIZE) then
							local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, ThreeTypeAnalyzer.TUPLE_SIZE);
							tupleCards:addCards(removedCardList);
						else
							local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, valueTempNum);
							local needLaiziCardNum = ThreeTypeAnalyzer.TUPLE_SIZE - valueTempNum;
							for i = 1,needLaiziCardNum do -- // 用了癞子才加上，不会任意补全（癞子不会去替代玩家已有的顺子中的元素）
								local laiziCardCopy = table.remove(useLaiziCardsCopy,1);
								laiziCardCopy:changeCard(valueTemp);
								table.insert(removedCardList,laiziCardCopy);
							end
							tupleCards:addCards(removedCardList);
						end
					end
					--// 是否所有头部顺子都是癞子 ******带56，去重
					local isAllTupleCardLaiz = true;
					for _,tupleCard in ipairs(tupleCards.cardList) do
						if (not tupleCard:isLazi()) then
							isAllTupleCardLaiz = false;
						end
					end
					local remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardsCopy);
					--// 寻找相应的几张单牌
					local takenCardsList = fourTakePairTypeAnalyzer:repeatSelectPairCards(remainCards, tupleNum, term);
					local subPartLenResult = {} -- // 部分长度的结果 
					for _,takenCards in ipairs(takenCardsList) do
						local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
						local resultKey = tupleNum * TUPLE_WEIGHT;
						if (isAllTupleCardLaiz) then
							resultKey = resultKey + TUPLE_WEIGHT * 4; -- // 这里随便给个值表示头部全是癞子 
							for _,card in ipairs(takenCards.cardList) do
								if (card:isLazi()) then -- // 癞子权重，区分癞子变成的5 和 原本就是5
									resultKey =  resultKey + card:getValue() * LAIZI_WEIGHT;
								else 
									resultKey =  resultKey + card:getValue();
								end
							end
						else 
							for _,card in ipairs(resultCards) do
								if (card:isLazi()) then --// 癞子权重，区分癞子变成的5 和 原本就是5
									resultKey = resultKey + card:getValue() * LAIZI_WEIGHT;
								else 
									resultKey = resultKey + card:getValue();
								end
							end
						end
						if (not exsitKeys[resultKey] 
								and self:match(resultCards, term)) then
							exsitKeys[resultKey] = true ;
							--// 保证排序
							resultCards:getResult():setSortFirstValue(firstSortValue);
							self:analysize(resultCards, term);
							table.insert(subPartLenResult,resultCards);
						end
					end
					--partLenResult.addAll(0, subPartLenResult); // 这里要逆序保证小的在前面
					for i=#subPartLenResult, 1 ,-1 do
						table.insert(partLenResult,1,subPartLenResult[i]);
					end
				end
			end
			--cardsResult.addAll(partLenResult);
			table.addAll(cardsResult,partLenResult);
		end
	end
	return cardsResult;
end








return ThreeTakePairPlusTypeAnalyzer;

